#include "crossbit/Profiler.h"
#include "crossbit/VInst.h"
#include "crossbit/common.h"
#include "vector"
using namespace crossbit;
Profiler::Profiler(){
}
Profiler::~Profiler(){
}
VBlock* Profiler::buildSuperVBlock( TCache* cache , XTMemAddr spc ){
		VBlock* head = new VBlock( spc );
		XTMemAddr branch, follow;
		std::vector<XTMemAddr> chain;
		std::vector<XTMemAddr> Tchain;
		XTMemAddr Tspc = spc;
		//changed on 2008-8-28
		for( int i = 0 ; i < GLOBAL::MAX_BLOCK_CHAIN_NUM ; i++ ){
				VBlock *vblock =  cache -> lookupVBlock( spc );
				if( cache -> lookupTBlock( spc ) -> isSupperBlock() ) break;
				if( vblock == NULL ) break;
				
				int j = 0;
				for( ; j < chain.size() ; j++ ) if( chain[j] == spc ) break;
				if( j < chain.size() ) break;

				chain.push_back(spc);

				VBlock::vb_reverse_iterator it = vblock -> rbegin(); 
				if( (*it) -> getOpcode() != OP_BRANCH || (*it) -> getOperand(4).reg != 0 )
						break;

				branch = (*it) -> getOperand(5).imm;
				follow = vblock -> nextSPC();
				
				TBlock *branch_tblock = cache -> lookupTBlock( branch );
				TBlock *follow_tblock = cache -> lookupTBlock( follow );
				if( branch_tblock == NULL && follow_tblock == NULL )
						break;
//				printf("%x ", spc);

				XTUint32 branch_count = 0;
				XTUint32 follow_count = 0;

				if( branch_tblock != NULL )
						branch_count = branch_tblock -> getRunCount();
				if( follow_tblock != NULL )
						follow_count = follow_tblock -> getRunCount();
				if( branch_count + follow_count < 0.8 * GLOBAL::THRESHOLD )
						break;
				if( follow_count > branch_count )
						spc = follow;
				else
						spc = branch;			


		}  //  */ 
 //       printf("\n");		
		//super block like dynamo
/*		spc = Tspc;
		for( int i = 0 ; i < GLOBAL::MAX_BLOCK_CHAIN_NUM ; i++ ){
				VBlock *vblock =  cache -> lookupVBlock( spc );
//				vblock -> print( std :: cout );
//				printf("\n");
				if( vblock == NULL ) break;
				if( cache -> lookupTBlock( spc ) -> isSupperBlock() ){
		//				 printf("stop cause : next block is super block\n");
						 break;
				}

				int j = 0;
				for( ; j < chain.size() ; j++ ) if( chain[j] == spc ){
		//				 printf("stop cause : next block already in chain\n");
						 break;
				}
				if( j < chain.size() ) break;

				chain.push_back(spc);
				//printf("%x " , spc );
				VBlock::vb_reverse_iterator it = vblock -> rbegin(); 
				if( (*it) -> getOpcode() == OP_BRANCH && (*it) -> getOperand(4).reg != 0 ){
		//				printf("stop cause : op = branch , indirect jmp\n");
						break;
				}
				if( (*it) -> getOpcode() != OP_BRANCH && (*it) -> getOpcode() != OP_JMP ){
	//			if( (*it) -> getOpcode() != OP_BRANCH){
		//				printf("stop cause : op != branch , op != jmp\n");
						break;
				}

		        spc = cache -> lookupTBlock( spc ) -> getLastExit().next;
		}  //  */	


		if( chain.size() == 0 ){
			     	
				return NULL;
		} 
//		printf("super block chain lenth = %d\n" , chain.size() );
		bool vreg[100] = {0};
		for( int i = 0 ; i < chain.size(); i++ ){
				VBlock *vblock = cache -> lookupVBlock( chain[i] );
				VBlock::vb_iterator left = vblock -> begin();

				while( left != vblock -> end() ){
						if( (*left) -> getOpcode() == OP_GET ){
							 int x = ((*left) -> getOperand(1)).reg;
							 if( vreg[x] ) {
									++left;
									continue;
							 }
							 vreg[x] = true;
						} // */
						if( (*left) -> getOpcode() == OP_PUT ){
							 int x = (*left) -> getOperand(1).reg;
							 vreg[x] = true;
						}
						head -> push_back( *left );
						++left;
				}
			    //printf("add = %x\n" , chain[i] );	
				//vblock -> print( std::cout );
				if( i == chain.size() - 1 ){
						head -> setVbNextSpc( vblock -> nextSPC() );
						break;
				} 
				if( (*(head -> rbegin())) -> getOpcode() == OP_BRANCH ) {
					if( vblock -> nextSPC() != chain[i+1] ){
						
							VBlock::vb_reverse_iterator it = head -> rbegin();
							Operand ccp = (*it) -> getOperand( 1 );

							if( ccp.cc == EQ ) ccp.cc = NE;
							else if( ccp.cc == NE ) ccp.cc = EQ;
							else if( ccp.cc == GT ) ccp.cc = LE; 
							else if( ccp.cc == LE ) ccp.cc = GT; 
							else if( ccp.cc == GE ) ccp.cc = LT; 
							else if( ccp.cc == LT ) ccp.cc = GE; 
							else if( ccp.cc == AB ) ccp.cc = BE; 
							else if( ccp.cc == BE ) ccp.cc = AB; 

							Operand opr_2 = (*it) -> getOperand(2);
							Operand opr_3 = (*it) -> getOperand(3);
							Operand opr_4 = (*it) -> getOperand(4);
						
					    	VInst* vinst = VInst5::createBRANCH( ccp.cc , opr_2.reg , opr_3.reg , opr_4.reg, vblock -> nextSPC()); 
							head -> erase( --(head -> end()) );
							head -> push_back( vinst ); 
					}
				} else {
							// The case of JMP					   		
							VBlock::vb_reverse_iterator it = head -> rbegin();
							head -> erase( --(head -> end()) );
							Operand opr_1 = (*it) -> getOperand( 1 );
							if( opr_1.reg != 0 ){
							    head -> push_back( VInst2 :: createLI( (*it) -> getOperand(2).imm , 36, s32) );
								head -> push_back( VInst3 :: createADD( 36 , opr_1.reg , 36, s32) );
								head -> push_back( VInst2 :: createLI( chain[i+1] , 37, s32) );
								head -> push_back( VInst5 :: createBRANCH( NE , 36 , 37, 36 , 0 ) ); 	
							}

				}
		}
//	   head -> print( std::cout );	
//   	printf("\n\n\n");	
		
		return head;
}	


